﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="CRUDServices.cs" company="DissingNelleman">
//   
// All rights reserved. </copyright>
// <summary>
//   The crud services.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace ServiceLibrary
{
    using System;
    using System.ServiceModel;
    using System.ServiceModel.Activation;

    using ServiceLibrary.Actioners.Base;
    using ServiceLibrary.Hibernate;
    using ServiceLibrary.Models.Domain;
    using ServiceLibrary.Services;
    using ServiceLibrary.Services.Queries;
    using ServiceLibrary.Services.Results;
    using System.Collections.Generic;

    /// <summary>
    /// The crud services.
    /// </summary>
    [ServiceBehavior(Name = "CRUDServices", InstanceContextMode = InstanceContextMode.PerCall,
        ConcurrencyMode = ConcurrencyMode.Multiple)]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class CRUDServices : ICRUDServices
    {
        #region Public Methods and Operators

        /// <summary>
        /// The execute command.
        /// </summary>
        /// <param name="command">
        /// The command.
        /// </param>
        /// <exception cref="Exception">
        /// May throw an exception
        /// </exception>
        public void ExecuteCommand(ICommand command)
        {
            // NHibernateProvider.Instance.UpdateDB();
            if (!this.ValidateUser())
            {
                return;
            }

            var cuID = GetHeader<string>("UserID", "ns");
            var currentUserID = new Guid(cuID);

            if (currentUserID == Guid.Empty)
            {
                return;
            }

            NHibernateProvider.Instance.WithSessionAndTransaction(
                hsession =>
                {
                    var ua = new UserActioner(hsession, null);
                    User activeUser = ua.GetUser(currentUserID);
                    if (activeUser == null)
                    {
                        throw new Exception("Brugeren findes ikke.");
                    }

                    command.Execute(hsession, activeUser);
                });
        }

        /// <summary>
        /// The execute command.
        /// </summary>
        /// <param name="command">
        /// The command.
        /// </param>
        /// <exception cref="Exception">
        /// May throw an exception
        /// </exception>
        public void ExecuteBatchsCommands(List<ICommand> commands)
        {
            // NHibernateProvider.Instance.UpdateDB();
            if (!this.ValidateUser())
            {
                return;
            }

            var cuID = GetHeader<string>("UserID", "ns");
            var currentUserID = new Guid(cuID);

            if (currentUserID == Guid.Empty)
            {
                return;
            }

            NHibernateProvider.Instance.WithSessionAndTransaction(
                hsession =>
                {
                    var ua = new UserActioner(hsession, null);
                    User activeUser = ua.GetUser(currentUserID);
                    if (activeUser == null)
                    {
                        throw new Exception("Brugeren findes ikke.");
                    }

                    foreach (var command in commands)
                    {
                        command.Execute(hsession, activeUser);
                    }
                });

        }

        /// <summary>
        /// The implementation of the query.
        /// </summary>
        /// <param name="query">
        /// The query.
        /// </param>
        /// <returns>
        /// The <see cref="IResult"/>.
        /// </returns>
        public IResult Query(IQuery query)
        {
            // NHibernateProvider.Instance.UpdateDB();
            if (!this.ValidateUser())
            {
                var set = new IResult { InvalidUsernameOrPassword = true };
                return set;
            }

            if (query == null)
            {
                return new IResult();
            }

            // ReSharper disable ConvertClosureToMethodGroup
            return NHibernateProvider.Instance.WithSession(hsession => query.Execute(hsession));
            // ReSharper restore ConvertClosureToMethodGroup
        }

        #endregion

        #region Methods

        /// <summary>
        /// The get header.
        /// </summary>
        /// <param name="name">
        /// The name.
        /// </param>
        /// <param name="ns">
        /// The ns.
        /// </param>
        /// <typeparam name="T">
        /// The type of the header that we want to retrieve.
        /// </typeparam>
        /// <returns>
        /// The <see cref="T"/>.
        /// </returns>
        private static T GetHeader<T>(string name, string ns)
        {
            return OperationContext.Current.IncomingMessageHeaders.FindHeader(name, ns) > -1
                       ? OperationContext.Current.IncomingMessageHeaders.GetHeader<T>(name, ns)
                       : default(T);
        }

        /// <summary>
        /// The validate user.
        /// </summary>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        private bool ValidateUser()
        {
            var username = GetHeader<string>("UserName", "ns");
            var encryptedPassword = GetHeader<string>("UserPassword", "ns");

            return NHibernateProvider.Instance.WithSession(
                hsession =>
                {
                    var userActioner = new UserActioner(hsession, null);
                    var validationQuery = new ValidateUserQuery
                                              {
                                                  Username = username,
                                                  Password = encryptedPassword
                                              };
                    return userActioner.ValidateLoginBoolean(validationQuery);
                });
        }

        #endregion
    }
}